package com.dream21th.dream21thredis.aspect;

import java.lang.reflect.Method;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.CodeSignature;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.annotation.Order;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Component;
import com.dream21th.dream21thredis.annotation.RedisDisLock;
import com.dream21th.dream21thredis.lock.RedisLock;
import com.dream21th.dream21thredis.util.AnnotationResolver;

import lombok.extern.slf4j.Slf4j;

/**
 * 切面类
 * @author lfy
 * 
 * @Aspect： 告诉Spring当前类是一个切面类
 *
 */
@Slf4j
@Aspect
@Order(1)
@Component
public class RedisLockAspect {
	@Autowired
	private RedisTemplate<Object, Object> redisTemplate;
	//抽取公共的切入点表达式
	//1、本类引用
	//2、其他的切面引用
	@Pointcut("@annotation(com.dream21th.dream21thredis.annotation.RedisDisLock)")
	public void pointCut(){};
	
	/**
	 * Around环绕通知
	 * @param joinPoint
	 */
	@Around("pointCut()")
	public Object logStart(ProceedingJoinPoint joinPoint){
		MethodSignature signature = (MethodSignature) joinPoint.getSignature();
        Method method = signature.getMethod();
        RedisDisLock annotation = method.getAnnotation(RedisDisLock.class);
		Object[] args = joinPoint.getArgs();
		String key=annotation.key();
		String prefix=annotation.prefix();
		String[] paramNames=((CodeSignature)joinPoint.getSignature()).getParameterNames();
		Class[] classs=((CodeSignature)joinPoint.getSignature()).getParameterTypes();
        
		key=(String)AnnotationResolver.newInstance().resolver(joinPoint, key);
		key=prefix.concat(key);
		log.info("分布式的key是：{}",key);
		RedisLock lock = new RedisLock(redisTemplate, key, annotation.timeoutMsecs(), annotation.expireMsecs());
		Object result=null;
		try {
			if(lock.lock()){
				result=joinPoint.proceed(args);
			}
		} catch (Throwable e) {
			e.printStackTrace();
		}finally {
			if(!lock.isExpired()){
				lock.unlock();
			}
		}
		return result;
	}
	
}
